#!/usr/bin/env bash
set -e

SERVER=$1
ROLES=$2
BRANCH=$3
if [ -z "$SERVER" ] || [ -z "$ROLES" ]; then
    echo "USAGE: $0 server roles [branch]"
    echo
    echo "Installs an empty Ubuntu server in AWS with a Zulip server role."
    echo
    echo " * server is the local part of the hostname (e.g. postgres0)"
    echo " * roles is a comma-separated list of Puppet rules to be passed to scripts/lib/install"
    echo "   E.g. 'zulip::profile::postgresql'"
    echo " * branch is used to override the default branch to install from."
    echo
    echo "Reads configuration from $HOME/.zulip-install-server.conf, which should look like:"
    echo
    echo "[repo]"
    echo "repo_url=git@github.com:zulip/zulip.git"
    echo "branch=master"
    echo "[aws]"
    echo "zone_id=Z2U988IEXAMPLE"
    echo "security_groups=sg-01234567"
    echo "image_id=ami-0dc45e3d9be6ab7b5"
    echo "instance_type=m4.large"
    echo "ssh_secret_id=prod/git/deploy"
    exit 1
fi
set -x

cd "$(dirname "$0")"

source ./bootstrap-awscli

zulip_install_config_file="$HOME/.zulip-install-server.conf"
if [ ! -f "$zulip_install_config_file" ]; then
    echo "No configuration file found in $zulip_install_config_file"
    exit 1
fi
REPO_URL=$(crudini --get "$zulip_install_config_file" repo repo_url)
if [ -z "$BRANCH" ]; then
    BRANCH=$(crudini --get "$zulip_install_config_file" repo default_branch)
fi

AWS_ZONE_ID=$(crudini --get "$zulip_install_config_file" aws zone_id)
SECURITY_GROUPS=$(crudini --get "$zulip_install_config_file" aws security_groups)
AMI_ID=$(crudini --get "$zulip_install_config_file" aws image_id)
INSTANCE_TYPE=$(crudini --get "$zulip_install_config_file" aws instance_type)
SSH_SECRET_ID=$(crudini --get "$zulip_install_config_file" aws ssh_secret_id)

# Verify it doesn't exist already
ZONE_NAME=$($AWS route53 get-hosted-zone --id "$AWS_ZONE_ID" | jq -r '.HostedZone.Name')
HOSTNAME="$SERVER.${ZONE_NAME%?}" # Remove trailing .
EXISTING_RECORDS=$($AWS route53 list-resource-record-sets \
    --hosted-zone-id "$AWS_ZONE_ID" \
    --query "ResourceRecordSets[?Name == '$HOSTNAME.']" \
    | jq '. | length')
if [ "$EXISTING_RECORDS" != "0" ]; then
    echo "$HOSTNAME already exists!"
    exit 1
fi

# Build up the provisioning script
BOOTDATA=$(mktemp)
{
    echo "#!/bin/bash"
    echo "SERVER=$SERVER"
    echo "HOSTNAME=$HOSTNAME"
    echo "ROLES=$ROLES"
    echo "REPO_URL=$REPO_URL"
    echo "BRANCH=$BRANCH"
    echo "SSH_SECRET_ID=$SSH_SECRET_ID"
    sed '/^AWS=/ r ./bootstrap-awscli' bootstrap-aws-installer
} >>"$BOOTDATA"

TAGS="[{Key=Name,Value=$SERVER},{Key=role,Value=\"$ROLES\"}]"
INSTANCE_DATA=$($AWS ec2 run-instances \
    --iam-instance-profile 'Name="EC2ProdInstance"' \
    --image-id "$AMI_ID" \
    --instance-type "$INSTANCE_TYPE" \
    --security-group-ids "$SECURITY_GROUPS" \
    --tag-specifications "ResourceType=instance,Tags=$TAGS" \
    --user-data "file://$BOOTDATA")
INSTANCEID=$(echo "$INSTANCE_DATA" | jq -r .Instances[0].InstanceId)

# Wait for public IP assignment
PUBLIC_DNS_NAME=""
while [ -z "$PUBLIC_DNS_NAME" ]; do
    sleep 1
    PUBLIC_DNS_NAME=$($AWS ec2 describe-instances --instance-ids "$INSTANCEID" \
        | jq -r .Reservations[0].Instances[0].PublicDnsName)
done

# Add the hostname to the zone
ROUTE53_CHANGES=$(mktemp)
cat >"$ROUTE53_CHANGES" <<EOF
{
    "Comment": "Add the $HOSTNAME CNAME record",
    "Changes": [
        {
            "Action": "CREATE",
            "ResourceRecordSet": {
                "Name": "$HOSTNAME",
                "Type": "CNAME",
                "TTL": 300,
                "ResourceRecords": [{"Value": "$PUBLIC_DNS_NAME"}]
            }
        }
    ]
}
EOF
$AWS route53 change-resource-record-sets --hosted-zone-id "$AWS_ZONE_ID" --change-batch "file://$ROUTE53_CHANGES"
rm "$ROUTE53_CHANGES"

set +x
echo
echo
echo ">>> Install started successfully!  Provisioning takes 5-6min."
echo "    sleep 360 && ssh root@$HOSTNAME"
